package net.dodoman.transactio;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class TransactionUtil {
	
	private final static ThreadLocal local = new ThreadLocal();
	
	private static Log log = LogFactory.getLog(TransactionUtil.class);

	/**
	 * 开启事务
	 */
	public static void startTransaction() throws BusinessException {
		Transaction tran = (Transaction) local.get();
		// 判断此事务是否属于一个顶层事务。
		if (tran == null) {
			tran = new Transaction();
			// 设置本地线程的connection
			Connection con = ConnectionPoolBean.getConnection();
			try {
				con.setAutoCommit(false);
			} catch (SQLException e) {
				e.printStackTrace();
				throw new BusinessException(e, "开启事务失败！");
			}
			tran.setConnection(con);
			tran.setCommitCount(0);
			tran.setTransCount(1);
			tran.setTransDeep(1);
			local.set(tran);
		} else {
			// 事务已经开启，将嵌套层次深度加一，将事务次数加一
			tran.setTransCount(tran.getTransCount() + 1);
			tran.setTransDeep(tran.getTransDeep() + 1);
		}
	}

	/**
	 * 提交事务
	 * 
	 */
	public static void commitTransaction() throws BusinessException {
		Transaction tran = (Transaction) local.get();
		// 如果事务属于嵌套，则不提交数据，直接将层次数减一。
		if (tran.getTransDeep() > 1) {
			tran.setTransDeep(tran.getTransDeep() - 1);
			tran.setCommitCount(tran.getCommitCount() + 1);
			return;
		}

		Connection con = tran.getConnection();
		try {
			if (tran.hasFullExecute()) {
				con.commit();
			}
		} catch (SQLException e) {
			log.error(e);
			throw new BusinessException(e, "提交事务失败!");
		}
	}

	/**
	 * 结束事务
	 * 
	 */
	public static void endTransaction() throws BusinessException {
		Transaction tran = (Transaction) local.get();
		// 如果事务属于嵌套，则不关闭连接，直接将层次数减一。
		if (tran.getTransDeep() > 1) {
			tran.setTransDeep(tran.getTransDeep() - 1);
			return;
		}

		// 当前事务已经结束，清空ThreadLocal变量，防止下一次操作拿到已经关闭的Connection对象。
		local.set(null);
		Connection con = tran.getConnection();
		try {
			if (!tran.hasFullExecute()) {
				con.rollback();
			}
		} catch (SQLException e) {
			log.error(e);
			throw new BusinessException(e, "事务回滚失败!");
		} finally {
			try {
				con.close();
			} catch (SQLException se) {
				log.error(se);
				throw new BusinessException(se, "关闭事务失败!");
			}
		}

	}

	/**
	 * 获取当前事务的数据库连接。
	 * 
	 * @return
	 */
	public static Connection getConnection() {
		Transaction tran = (Transaction) local.get();
		Connection con = tran.getConnection();
		if (con == null) {
			con = ConnectionPoolBean.getConnection();
		}
		return con;
	}

	/**
	 * 测试代码
	 * 
	 * @param args
	 * @throws Exception
	 */
	public static void main(String args[]) throws Exception {
		test();
		test();
	}

	/**
	 * 测试代码
	 * 
	 */
	private static void test() {
		TransactionUtil.startTransaction();
		try {
			Connection con = TransactionUtil.getConnection();
			Statement stmt = con
					.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
							ResultSet.CONCUR_UPDATABLE);
			stmt.executeUpdate("INSERT INTO bb(bb) values('bb')");
			stmt.executeUpdate("INSERT INTO aa(aa) values('aa')");
			// if(true) throw new Exception("");
			TransactionUtil.commitTransaction();
		} catch (Exception e) {
			e.printStackTrace();
			// throw new BusinessException("");
		} finally {
			TransactionUtil.endTransaction();
		}
	}
}
